#ifndef BANK_ACCOUNT_HH
#define BANK_ACCOUNT_HH

#include <string>
#include <vector>
#include "Transaction.hh"

namespace BankingSystem {

class BankAccount {
protected:
    std::string accountId;         // Unique account identifier
    std::string ownerName;         // Account holder's name         
    std::vector<Transaction> transactions; // Transaction history

public:
    double balance; 
    BankAccount(const std::string& id, const std::string& owner, double initialBalance = 0.0);
    virtual ~BankAccount() = default;

    // Pure virtual functions for account operations
    virtual bool deposit(double amount, const std::string& note = "") = 0;
    virtual bool withdraw(double amount, const std::string& note = "") = 0;
    virtual bool transferTo(BankAccount* destination, double amount, const std::string& note = "") = 0;

    // Getters
    std::string getAccountId() const { return accountId; }
    std::string getOwnerName() const { return ownerName; }
    double getBalance() const { return balance; }
    const std::vector<Transaction>& getTransactions() const { return transactions; }

    // Transaction and reporting methods
    void addTransaction(const Transaction& transaction);
    virtual std::string getAccountType() const = 0;
    bool generateReport(const std::string& filename) const;
};

class SavingsAccount : public BankAccount {
public:
    SavingsAccount(const std::string& id, const std::string& owner, double initialBalance = 0.0);
    bool deposit(double amount, const std::string& note = "") override;
    bool withdraw(double amount, const std::string& note = "") override;
    bool transferTo(BankAccount* destination, double amount, const std::string& note = "") override;
    std::string getAccountType() const override { return "Savings"; }
};

class CheckingAccount : public BankAccount {
public:
    CheckingAccount(const std::string& id, const std::string& owner, double initialBalance = 0.0);
    bool deposit(double amount, const std::string& note = "") override;
    bool withdraw(double amount, const std::string& note = "") override;
    bool transferTo(BankAccount* destination, double amount, const std::string& note = "") override;
    std::string getAccountType() const override { return "Checking"; }
};

} // namespace BankingSystem

#endif // BANK_ACCOUNT_HH